classdef dotsAllRemoteObjectManagersTestable < dotsAllRemoteObjectManagers
    % Concrete subclass of dotsAllRemoteObjectManagers for testing. Can be
    % cross-wired to a "remote" instance, to veryfy transaciton results.
    
    properties
        acknowledgePropertyChangeFunction;
        counterpart;
        name;
        
        testProperty;
        testMethodResult;
    end
    
    methods (Access = private)
        function self = dotsAllRemoteObjectManagersTestable
            self.initialize;
        end
    end
    
    methods (Access = protected)
        
        function configureSockets(self)
            if ~self.clientMode && ~self.serverMode
                % cross-wire transactions to counterparts
                self.sendTransactionAsClientFunction = @letCounterpartDoTransaction;
                self.sendTransactionAsServerFunction = @letCounterpartAcknowledgeTransaction;
                
            else
                % send transaction messages
                self.sendTransactionAsClientFunction = @sendTransactionAsClient;
                self.sendTransactionAsServerFunction = @sendTransactionAsServer;
            end
        end
        
        function sendTransactionAsClient(self, txn)
            %disp(sprintf('%s send %s', self.name, txn.UID));
            self.sendTransactionAsClient@dotsAllRemoteObjectManagers(txn);
            self.counterpart.receiveTransactionsAsServer(true);
        end

        function sendTransactionAsServer(self, txn)
            self.sendTransactionAsServer@dotsAllRemoteObjectManagers(txn);
            self.counterpart.receiveTransactionsAsClient(true);
        end
        
        function acknowledgeTransaction(self, txn)
            self.acknowledgeTransaction@dotsAllRemoteObjectManagers(txn);
            %disp(sprintf('%s ack %s', self.name, txn.UID));
        end
    end
    
    methods
        function openClientSocket(self)
            self.clientSocket = self.theMessenger.openDefaultClientSocket;
        end

        function openServerSocket(self)
            self.serverSocket = self.theMessenger.openDefaultServerSocket;
        end
        
        function letCounterpartDoTransaction(self, txn)
            self.counterpart.doTransactionForCounterpart(txn);
        end

        function doTransactionForCounterpart(self, txn)
            self.doTransaction(txn);
        end
        
        function letCounterpartAcknowledgeTransaction(self, txn)
            self.counterpart.acknowledgeTransactionForCounterpart(txn);
        end
        
        function acknowledgeTransactionForCounterpart(self, txn)
            self.acknowledgeTransaction(txn);
        end
        
        function acknowledgePropertyChange(self, object, property)
            self.acknowledgePropertyChange@dotsAllRemoteObjectManagers(object, property);
            if ~isempty(self.acknowledgePropertyChangeFunction)
                feval(self.acknowledgePropertyChangeFunction, object, property);
            end
        end
        
        function testMethod(self, arg)
            self.testMethodResult = arg;
            self.callToCounterpart('testMethod', arg);
        end            
        
        function set.testProperty(self, testProperty)
            self.testProperty = testProperty;
            self.forwardToCounterpart('testProperty', testProperty)
        end
    end
    
    methods (Static)
        function om = theObject
            % not really a singleton
            om = dotsAllRemoteObjectManagersTestable;
        end
        
        function reset
            self = dotsAllRemoteObjectManagersTestable.theObject;
            self.initialize;
        end
        
        function g = gui
            self = dotsAllRemoteObjectManagersTestable.theObject;
            g = self.managedObjects.gui;
        end
    end
end